#include <incctrls.h>
#include <inctypes.h>

/*********************************************************************************
 * 
 * krl_idle_main - 空转函数主函数
 * 
 * DESCRIPTION
 * 运行在内核态, 可以直接调用进程调度哈数, 有单独的thread_t结构体和内核栈
 */

static void krl_idle_main (void)
    {
    
    /* 进程永不退出 */

    FOREVER
        {
        kprintf ("idle is run\r\n");

        /* 进程调度函数 */

        krl_sched_run ();
        }

    /* never be here */

    return;
    }

/*********************************************************************************
 * 
 * create_idle_thread - 创建空闲进程核心函数
 * 
 * DESCRIPTION
 */

static thread_t * create_idle_thread (void)
    {
    bool_t     access     = FALSE;
    thread_t * thdp       = NULL;
    size_t     usrstksz   = 0, krlstksz = 0;
    addr_t     usrstkaddr = NULL, krlstkaddr = NULL;

    /* 分配用户栈 */

    usrstkaddr = krl_mem_new (usrstksz);

    if (usrstkaddr == NULL)
        {
        return NULL; /* 分配失败 */
        }

    /* 分配内核栈 */

    krlstkaddr = krl_mem_new (krlstksz);

    if (krlstkaddr == NULL)
        {
        goto krlstk_create_fail;  /* 分配内核栈失败, 释放用户栈 */
        }

    /* 分配进程描述符 */

    thdp = krl_create_thddsc ();

    if (thdp == NULL)
        {
        goto thddsc_create_fail;  /* 创建进程描述符失败, 释放用户栈和内核栈 */
        }

    /* 初始化成员变量 */

    thdp->privalege = THDPRE_SYS;       /* 用户权限设置 (未实现进程权限检查) */
    thdp->priority  = THDPRI_MAX;       /* 空闲进程的优先级为最低 */
    thdp->cpuid     = hal_get_cpuid (); /* 设置进程所在的CPU ID  */

    /* 设置用户栈和内核栈的栈顶地址和栈的开始地址 */

    thdp->usrstktop   = usrstkaddr + (addr_t) (usrstksz - 1);
    thdp->usrstkstart = usrstkaddr;
    thdp->krlstktop   = krlstkaddr + (addr_t) (krlstksz - 1);
    thdp->krlstkstart = krlstkaddr;

    /* 进程内核栈初始化 */

    krl_thdkrlstk_init (thdp, (void *) krl_idle_main, DAFT_CPSR, DAFT_SPSR);

    /* 利用 cpu id 找到对应 的 schdata_t 结构体 */

    schdata_t * schdp    = &osschclass.schdata[thdp->cpuid];
    schdp->curcpuidlethd = thdp;   /* 指定该CPU空闲进程为 thdp */
    schdp->curcpurunthd  = thdp;   /* 标识当前cpu正在运行的进程为 thdp */

    /* 创建成功, 返回进程描述符 */

    return thdp;

thddsc_create_fail:

    /* 释放内核栈 */

    if (krl_mem_delete (krlstkaddr, krlstksz) == FALSE)
        {
        krl_system_die ("create_idle_thread err\r\n");
        return NULL;
        }

krlstk_create_fail:

    /* 释放用户栈 */

    if (krl_mem_delete (usrstkaddr, usrstksz) == FALSE)
        {
        krl_system_die ("create_idle_thread err\r\n");
        return NULL;
        }

    return NULL;
    }

/*********************************************************************************
 * 
 * krl_idle_start - 运行空转进程
 * 
 * DESCRIPTION
 * 开始运行空转进程
 */

static void krl_idle_start (void)
    {

    /* 获取当前CPU的ID号 */

    uint_t cpuid = hal_get_cpuid ();

    /* 获得当前CPU的 schdata_t 结构体指针 */

    schdata_t * schdp = &osschclass.schdata[cpuid];

    /* 获取当前进程的 thread_t 进程 结构体指针 */

    thread_t * thdp = schdp->curcpuidlethd;

    /* 设置这个进程的状态为 运行态 */

    thdp->status = THDSTUS_RUN;

    /* 开始运行这个进程 */

    krl_sched_return_from_first_thd (thdp);

    /* can never be here */

    return;
    }

/*********************************************************************************
 * 
 * krl_create_idle - 创建一个空闲进程
 * 
 * DESCRIPTION
 */

static void krl_create_idle (void)
    {

    /* 创建空闲进程 */

    thread_t * thdidle = create_idle_thread ();

    if (thdidle == NULL)
        {
        krl_system_die ("create idle thread err\r\n");
        return;
        }

    /* 输出空转进程描述符地址表示创建成功 */

    kprintf ("IDLE_THREAD_TASK: 0x%x\r\n", (uint_t) thdidle);

    return;
    }

/*********************************************************************************
 * 
 * krl_idle_init - 创建并运行一个 idle 进程
 * 
 * DESCRIPTION
 * 创建并运行一个 idle 进程
 */

void krl_idle_init (void)
    {

    /* 创建一个空转进程 */

    krl_create_idle ();

    /* 开始运行该空转进程 */

    krl_idle_start ();

    return;    
    }
